package com.mkz.jbpm.activiti.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.identity.User;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.mkz.jbpm.activiti.ActTaskService;
import com.mkz.jbpm.activiti.base.ActServiceFactory;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;

/**
 * ClassName: ActTaseServiceImpl 
 * @Description: 流程任务实现类
 * @author: KuangJianyu
 * @date: 2020年4月3日
 */
@Component
public class ActTaskServiceImpl extends ActServiceFactory implements ActTaskService {
    @Autowired
    private ActHistTaskQueryServiceImpl actHistTaskQueryServiceImpl;

	@Override
	public void setVariableLocal(String taskId, String variableName, Object value) {
		taskService.setVariableLocal(taskId, variableName, value);
	}

	@Override
	public void setVariablesLocal(String taskId, Map<String, ? extends Object> variables) {
		taskService.setVariablesLocal(taskId, variables);
	}

	@Override
	public void claim(String taskId, String userId) throws Exception {
		taskService.claim(taskId, userId);
	}

	@Override
	public void unclaim(String taskId) throws Exception {
		taskService.unclaim(taskId);
	}

	@Override
	public void complete(String taskId) throws Exception {
		this.complete(taskId, null);
	}

	@Override
	public void complete(String taskId, Map<String, Object> variables) throws RuntimeException, Exception {
		taskService.complete(taskId, variables);
	}

	@Override
	public Map<String, Object> complete(String taskId, Map<String, Object> variables, boolean localScope) {
		HistoricTaskInstance finishTask = actHistTaskQueryServiceImpl.finishedTask(taskId);
        taskService.complete(taskId, variables, localScope);
        HistoricTaskInstance activeTask = actHistTaskQueryServiceImpl.activeTask(finishTask.getProcessInstanceId());
        Map<String, Object> map = MapUtil.newHashMap();
        map.put("finish", finishTask);
        map.put("active", activeTask);
        return map;
	}

	@Override
	public Boolean completeAndDealNext(String taskId, Map<String, Object> variables, String remark){
		HistoricTaskInstance finishTask = actHistTaskQueryServiceImpl.finishedTask(taskId);
		if(StrUtil.isNotBlank(remark)) {
			taskService.addComment(taskId, finishTask.getProcessInstanceId(), "remark", remark);
		}
        taskService.complete(taskId, variables);
        HistoricTaskInstance activeTask = actHistTaskQueryServiceImpl.activeTask(finishTask.getProcessInstanceId());
        Map<String, Object> map = MapUtil.newHashMap();
        map.put("finish", finishTask);
        map.put("active", activeTask);
        if(null!=activeTask) {
        	dealNextNodeCandidates(activeTask.getId());
        }
        return true;
	}
	
	@Override
	public void dealNextNodeCandidates(String taskId) {
        //3 通过流程实例获取“业务键”
        List<IdentityLink> newStepList = taskService.getIdentityLinksForTask(taskId);
        if(CollectionUtil.isNotEmpty(newStepList)) {
        	List<String> candidateUsers = new ArrayList<String>();
    		for(IdentityLink temp:newStepList) {
    			if(StrUtil.isNotBlank(temp.getUserId())) {
    				candidateUsers.add(temp.getUserId());
    			}else if(StrUtil.isNotBlank(temp.getGroupId())) {
        			//如果是候选组类类型，则需要将对应角色下的所有用户添加到用户组
    				List<User> usersInGroup = identityService.createUserQuery().memberOfGroup(temp.getGroupId()).list();
        			for(User tu:usersInGroup) {
        				candidateUsers.add(tu.getId());
        	        }
    			}
    		}
        	//只有一个候选人，则执行自动签收
    		if(candidateUsers.size()==1) {
    			taskService.claim(taskId, candidateUsers.get(0));
    		}else if(candidateUsers.size()>1) {
    			for(String userId:candidateUsers) {
    	        	taskService.addUserIdentityLink(taskId, userId, IdentityLinkType.CANDIDATE);
    	        }
    		}
        }
	}

	@Override
	public void setAssignee(String taskId, String userId) throws ActivitiObjectNotFoundException {
		taskService.setAssignee(taskId, userId);
	}

	@Override
	public void delegate(String taskId, String userId) {
		taskService.delegateTask(taskId, userId);
	}

	@Override
	public void resolveTask(String taskId) {
		taskService.resolveTask(taskId);
	}

	@Override
	public void setOwner(String taskId, String userId) {
		taskService.setOwner(taskId, userId);
	}

	@Override
	public void delete(String taskId) {
		taskService.deleteTask(taskId);
	}

	@Override
	public void deleteWithReason(String taskId, String reason) {
		taskService.deleteTask(taskId, reason);
	}

	@Override
	public void addCandidateUser(String taskId, String userId) throws Exception {
		taskService.addCandidateUser(taskId, userId);
	}

	@Override
	public Comment addComment(String taskId, String processInstanceId, String message) throws RuntimeException, Exception {
		return addComment(taskId, processInstanceId, null, message);
	}

	@Override
	public Comment addComment(String taskId, String processInstanceId, String type, String message) throws RuntimeException, Exception {
		if(StrUtil.isBlank(type)) {
			return taskService.addComment(taskId, processInstanceId, message);
		}
		return taskService.addComment(taskId, processInstanceId, type, message);
	}

	@Override
	public List<Comment> getTaskComments(String taskId) throws RuntimeException, Exception {
        return taskService.getTaskComments(taskId);
	}
}
